using System;
using System.Collections.Generic;
using System.Text;
using Csla;
using System.Data;
using Active.Core.DB;
using Csla.Data;
using Active.Core.State;
using DesignByContract;

namespace Active.Core
{
    /// <summary>
    /// Read only order info list.
    /// </summary>
    [Serializable()]
    public class OrderList :
      ReadOnlyListBase<OrderList, OrderInfo>
    {
        #region Paging

        private int _totalRecordsCount;
        /// <summary>
        /// Gets the total records count.
        /// </summary>
        /// <value>The total records count.</value>
        public int TotalRecordsCount
        {
            get
            {
                return _totalRecordsCount;
            }
        }

        private int _pageNo;
        /// <summary>
        /// Gets the page no.
        /// </summary>
        /// <value>The page no.</value>
        public int PageNo
        {
            get
            {
                return _pageNo;
            }
        }

        private int _pageSize;
        /// <summary>
        /// Gets the size of the page.
        /// </summary>
        /// <value>The size of the page.</value>
        public int PageSize
        {
            get
            {
                return _pageSize;
            }
        }

        private bool _allowPaging = false;
        /// <summary>
        /// Gets a value indicating whether [allow paging].
        /// </summary>
        /// <value><c>true</c> if [allow paging]; otherwise, <c>false</c>.</value>
        public bool AllowPaging
        {
            get
            {
                return _allowPaging;
            }
        }

        #endregion

        #region Authorization Rules

        /// <summary>
        /// Determines whether this instance [can get object].
        /// </summary>
        /// <returns>
        /// 	<c>true</c> if this instance [can get object]; otherwise, <c>false</c>.
        /// </returns>
        public static bool CanGetObject()
        {
            if (Csla.ApplicationContext.User.IsInRole("MediaEmployee")
                || Csla.ApplicationContext.User.IsInRole("MediaManager"))
            {
                return true;
            }
            return false;
        }

        #endregion

        #region Factory Methods

        /// <summary>
        /// Gets the order list.
        /// </summary>
        /// <param name="regionIds">The region ids.</param>
        /// <param name="year">The year.</param>
        /// <param name="month">The month.</param>
        /// <param name="pageNo">The page no.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <returns></returns>
        public static OrderList GetOrderList(int[] regionIds, int mediaId, int year, int month,
            int pageNo, int pageSize)
        {
            Check.Require(pageNo > 0);
            Check.Require(pageSize > 0);
            StateValue state;
            if (Utils.IsMediaEmployee || Utils.IsMediaManager)
            {
                state = StateValue.MediaEmployeeWorking;
            }
            else
            {
                throw new System.Security.SecurityException(Resource.CanNotGetOrderList 
                    + string.Format(" : {0}", Csla.ApplicationContext.User.Identity.Name));
            }
            return GetOrderList(regionIds, mediaId, year, month, state, pageNo, pageSize);
        }

        internal static OrderList GetOrderList(int[] regionIds, int mediaId, int year, int month, StateValue state,
            int pageNo, int pageSize)
        {
            Check.Require(pageNo > 0);
            Check.Require(pageSize > 0);
            return DataPortal.Fetch<OrderList>(
                new Criteria(regionIds, mediaId, year, month, state, pageNo, pageSize));
        }

        private OrderList()
        { /* require use of factory methods */ }

        #endregion

        #region Data Access

        [Serializable()]
        private class Criteria
        {
            private int[] _regionIds;
            public int[] RegionIds
            {
                get { return _regionIds; }
            }

            private int _mediaId;
            public int MediaId
            {
                get
                {
                    return _mediaId;
                }
            }

            private int _year;
            public int Year
            {
                get
                {
                    return _year;
                }
            }

            private int _month;
            public int Month
            {
                get
                {
                    return _month;
                }
            }

            private StateValue _state = StateValue.CustomerEmployeeWorking;
            public StateValue State
            {
                get
                {
                    return _state;
                }
            }

            private int _pageNo;
            public int PageNo
            {
                get
                {
                    return _pageNo;
                }
            }

            private int _pageSize;
            public int PageSize
            {
                get
                {
                    return _pageSize;
                }
            }

            private bool _allowPaging = false;
            public bool AllowPaging
            {
                get
                {
                    return _allowPaging;
                }
            }

            public Criteria(int[] regionIds, int mediaId, int year, int month, StateValue state,
                int pageNo, int pageSize)
            {
                _regionIds = regionIds;
                _mediaId=mediaId;
                _year = year;
                _month = month;
                _state = state;
                _pageNo = pageNo;
                _pageSize = pageSize;
                _allowPaging = true;
            }
        }

        private void DataPortal_Fetch(Criteria criteria)
        {
            RaiseListChangedEvents = false;
            IsReadOnly = false;
            NBearLite.SelectSqlSection select =
                DataService.DBService.Select(Tables.Orders,
                Tables.Orders.Id, Tables.Orders.BillId, Tables.Orders.PlayVersions,
                Tables.Orders.StartDate, Tables.Orders.EndDate, Tables.Orders.StateValue,
                Tables.Orders.MediaId, Tables.Orders.Number, 
                Tables.Medias.Name)
                .Join(Tables.Medias, Tables.Medias.Id == Tables.Orders.MediaId);
            NBearLite.WhereClip where = Tables.Orders.StateValue >= criteria.State;
            if (criteria.RegionIds != null && criteria.RegionIds.Length > 0)
            {
                NBearLite.WhereClip w = NBearLite.WhereClip.All;
                foreach (int id in criteria.RegionIds)
                {
                    w.Or(Tables.Medias.RegionId == id);
                }
                where.And(w);
                //where.And(Tables.Medias.RegionId.In(criteria.RegionIds));
            }
            if(criteria.MediaId>0)
            {
                where.And(Tables.Orders.MediaId == criteria.MediaId);
            }
            if (criteria.Year > 0)
            {
                where.And(Tables.Orders.StartDate.GetYear() == criteria.Year);
            }
            if (criteria.Month > 0)
            {
                where.And(Tables.Orders.StartDate.GetMonth() == criteria.Month);
            }
            if (criteria.AllowPaging)
            {
                select.SetSelectRange(criteria.PageSize,
                    (criteria.PageNo - 1) * criteria.PageSize,
                    Tables.Orders.Id);
                _allowPaging = true;
                _pageNo = criteria.PageNo;
                _pageSize = criteria.PageSize;
            }
            select.Where(where);
            select.OrderBy(Tables.Orders.Id.Desc);
            using (SafeDataReader dr = new SafeDataReader(select.ToDataReader()))
            {
                while (dr.Read())
                {
                    Add(OrderInfo.GetOrderInfo(dr));
                }
            }
            if (_allowPaging)
            {
                _totalRecordsCount = (int)DataService.DBService.Select(Tables.Orders,
                    Tables.Orders.Id.Count())
                    .Join(Tables.Medias, Tables.Medias.Id == Tables.Orders.MediaId)
                    .Where(where).ToScalar();
            }
            else
            {
                _totalRecordsCount = this.Count;
            }
            IsReadOnly = true;
            RaiseListChangedEvents = true;
        }

        #endregion
    }
}

